package com.java.java基础.线程;

/**
 * 互斥锁
 * 线程同步机制-synchronized锁：多线程情况下，同一时候一组敏感数据只有一个线程能操作，操作完后再释放锁才允许其他线程操作，synchronized锁避免数据不一致保证数据一致性
 * 1.synchronized(需要同步的对象) {
 *     需要同步的代码
 * }
 * 2.synchronized还可以在方法中声明来修饰方法-为同步方法
 * 3.synchronized还可以修饰静态方法-为静态同步方法
 * public static void main(String[] args) throws InterruptedException {
 *     synchronized(类.class){
 *         system.out.println(name);
 *     }
 * }
 * public synchronized static void method(String name) {
 *     需要同步的代码
 * }
 * 注意事项和细节
 * 1.同步方法如果没有使用static，则同步方法锁的是this，即当前对象，如果使用static，则同步方法锁的是类对象，即类.class
 * 1.11.同步方法如果有使用static，默认锁对象：当前类.class
 * 2.同步方法在调用的时候，会自动获取锁，调用结束后会自动释放锁
 * 3.同步方法在调用的时候，会自动获取锁，调用结束后会
 * 4.实现落地的同步代码块，需要先分析上锁的代码，
 * 然后分析上锁的代码，然后分析解锁的代码，然后分析上锁的代码和解锁的代码是否在同一个线程中，如果不在同一个线程中，则需要使用
 * 要求多个线程的缩对象同一个即可
 *
 * 目标：独立完成坦克大战
 */
public class ThreadS6 {
    public static void main(String[] args) throws InterruptedException {
        SynchronizedTest synchronizedTest1 = new SynchronizedTest();
        Thread thread = new Thread(synchronizedTest1 , "线程1");
        Thread thread2 = new Thread(synchronizedTest1 , "线程2");
        Thread thread3 = new Thread(synchronizedTest1 , "线程2");
        thread.start();
        thread2.start();
        thread3.start();
        thread.join(); // 等待三个线程结束后打印卖出总数
        thread2.join();
        thread3.join();
        System.out.println("sellNum: " + SynchronizedTest.sellNum);
    }
}

class SynchronizedTest implements Runnable {
    private static int ticketNum = 20; // 总票数
    public static int sellNum = 0; // 统计卖出总票数
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see Thread#run()
     */
    @Override
    public void run() {
        while (true) {
            if (ticketNum > 0) {
                System.out.println(Thread.currentThread().getName() + "卖出了一张票，剩余：" + --ticketNum);  // 卖出一张票
                sellNum++;  // 卖出总票数加1
            } else {
                break;
            }
            try {
                Thread.sleep(10);  // 每次sleep 10ms，提高出错可能
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
